/**
 * dttvb_chat script file.
 *
 * @copyright Copyright (C) 2008 the DtTvB (http://dt.in.th/)
 * @license http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
 * @package dttvb_chat
 */


// This is my world.
(function() {


	function $(_) { return document.getElementById(_); }

	var chats = $('chat_contents');
	var scroller = $('chat_data');
	var newalert = $('chat_new');
	var onlinelist = $('chat_onlines');
	var userids = {};
	function dtbbcode(text, element) {    
		/* DtBBCode by the DtTvB.
		   http://dt.in.th/2008-09-24.dtbbcode.html

		   Released under CC-BY-SA license.
		   http://creativecommons.org/licenses/by/3.0/
		 */

		if (text.match(/^\s*$/)) return;
		var o = 0;
		var t = [];
		var s = dtbbcode.tags;
		function str(x) {
			return {
				'type': 'text',
				'value': x
			};
		}
		text.replace(/\[(\/?)(\w+)(=(?:[^\]]+))?\]/g, function(aMatch, aClose, aName, aParam, aOffset) {
			if (aOffset > o) {
				t.push (str(text.substr(o, aOffset - o)));
			}
			o = aOffset + aMatch.length;
			if (aClose == '/' && aParam != '' && typeof aParam != 'undefined') {
				t.push (str(aMatch));
				return;
			}
			var nm = aName.toLowerCase();
			if (s[nm] === undefined) {
				t.push (str(aMatch));
				return;
			}
			var c = {
				'type': 'tag',
				'tag': s[nm],
				'mode': aClose == '/' ? 'close' : 'open'
			};
			if (aParam != '' && aParam !== undefined) {
				c.arg = aParam.substr(1);
			}
			t.push (c);
		});
		t.push (str(text.substr(o)));
		var stack = [];
		stack.push ([element, 'root']);
		function HTMLNODE(q) {
			var x = document.createElement('span');
			x.innerHTML = q;
			return x;
		}
		function process(i) {
			var c = t[i];
			var w = stack[stack.length - 1][0];
			if (c.type == 'text') {
				w.appendChild (HTMLNODE(c.value));
				return;
			}
			if (c.mode == 'open') {
				var el = document.createElement('span');
				w.appendChild (el);
				c.tag.applier (el, c.arg);
				stack.push ([el, c]);
				return;
			}
			if (c.mode == 'close') {
				if (stack.length <= 1) return;
				var meta = stack.pop();
				var el = meta[0];
				var d = meta[1];
				w = stack[stack.length - 1][0];
			}
		}
		for (var i = 0; i < t.length; i ++) {
			process (i);
		}
	}
	dtbbcode.tags = {
		'b': {
			id: 'bold',
			applier: function(el) {
				el.style.fontWeight = 'bold';
			}
		},
		'i': {
			id: 'italic',
			applier: function(el) {
				el.style.fontStyle = 'italic';
			}
		},
		'u': {
			id: 'underline',
			applier: function(el) {
				el.style.textDecoration = 'underline';
			}
		},
		's': {
			id: 'strike',
			applier: function(el) {
				el.style.textDecoration = 'line-through';
			}
		},
		'size': {
			id: 'fontsize',
			applier: function(el, arg) {
				if (arg === undefined) return;
				var sz = (((Math.max(1, Math.min(10, parseInt(arg))) - 3) * 0.2) + 1);
				var q = 1;
				el.style.fontSize = sz + 'em';
				el.style.lineHeight = '1.2em';
			}
		},
		'color': {
			id: 'fontcolor',
			applier: function(el, arg) {
				if (arg === undefined) return;
				var q = 0;
				var i = setInterval(function() {
					el.style.color = (++q % 2) ? arg : '';
					if (q == 5) clearInterval(i);
				}, 200);
			}
		}
	};
	
	function GiveMeXHR() {
		if (window.XMLHttpRequest)
			return new XMLHttpRequest();
		if (window.ActiveXObject) {
			try {
				return new ActiveXObject("Microsoft.XMLHTTP"); 
			} catch (e) {
				try {
					return new ActiveXObject("Msxml2.XMLHTTP");
				} catch (e2) {
					return false;
				}
			}
		}
		return false;
	}
	
	var latestID = 0;
	var chatElements = {};
	function ChatContainer() {
		var div = document.createElement('div');
		div.style.paddingBottom = '1ex';
		return div;
	}
	function ChatMessage(t, x, y) {
		if (y.substr(0, 4) == '/me ') {
			return StatusMessage(t, x, y.substr(4));
		}
		var div = ChatContainer();
		var el = {
			time: document.createElement('span'),
			name: document.createElement('span'),
			message: document.createElement('span')
		};
		el.time.style.color = '#888';
		el.name.style.fontWeight = 'bold';
		el.name.appendChild (document.createTextNode(x + ': '));
		el.time.appendChild (document.createTextNode('(' + t + ') '));
		dtbbcode(y, el.message);
		div.appendChild (el.time);
		div.appendChild (el.name);
		div.appendChild (el.message);
		chats.appendChild (div);
		return div;
	}
	function StatusMessage(t, x, y) {
		var div = ChatContainer();
		var el = {
			time: document.createElement('span'),
			name: document.createElement('span'),
			message: document.createElement('span')
		};
		el.time.style.color = '#888';
		el.name.style.fontWeight = 'bold';
		el.name.style.color = '#808';
		el.message.style.color = '#808';
		el.name.appendChild (document.createTextNode('* ' + x + ' '));
		el.time.appendChild (document.createTextNode('(' + t + ') '));
		el.message.appendChild (document.createTextNode(y));
		div.appendChild (el.time);
		div.appendChild (el.name);
		div.appendChild (el.message);
		chats.appendChild (div);
		return div;
	}
	function InfoMessage(x) {
		var div = ChatContainer();
		var el = {
			message: document.createElement('span')
		};
		el.message.style.fontWeight = 'bold';
		el.message.style.color = '#a00';
		el.message.appendChild (document.createTextNode('[Info] ' + x));
		div.appendChild (el.message);
		chats.appendChild (div);
		return div;
	}

	var form = $('chatform');
	form.onsubmit = function() {
		var msg = form.message.value;
		form.message.value = '';
		sendDataToServer ({
			'since_id': latestID,
			'message': msg
		});
		return false;
	};

	var sk = 0;
	function scrollKeeper() {
		clearTimeout (sk);
		sk = setTimeout(scrollKeeper2, 1);
	}
	function scrollKeeper2() {
		var mx = scroller.scrollHeight - scroller.offsetHeight + 10;
		var lf = mx - scroller.scrollTop;
		scroller.scrollTop += Math.max(2, Math.ceil(lf / 10));
		if (lf > 12) {
			sk = setTimeout(scrollKeeper2, 1);
		}
	}
	scroller.onscroll = function() {
		var inscrol = scroller.scrollTop + scroller.offsetHeight + 20 > scroller.scrollHeight;
		if (inscrol) {
			newalert.style.display = 'none';
		}
	};
	newalert.onclick = function() {
		scrollKeeper ();
	};

	function msgscroll() {
		var inscrol = scroller.scrollTop + scroller.offsetHeight + 20 > scroller.scrollHeight;
		if (inscrol) {
			scrollKeeper ();
		} else {
			newalert.style.display = 'block';
		}
	}
	function minorscroll() {
		var inscrol = scroller.scrollTop + scroller.offsetHeight + 20 > scroller.scrollHeight;
		if (inscrol) {
			scrollKeeper ();
		}
	}

	var lastList = {};
	var firstUpdate = 1;
	var responders = {
	
		'update': function(q) {
			var s = q.messages;
			var o = q.online;
			var x = '';
			for (var i in o) {
				x += '<div>-&nbsp; ' + o[i] + '</div>';
				if (lastList[i] === undefined) {
					minorscroll ();
					if (!firstUpdate) {
						InfoMessage (o[i] + ' has joined in.');
					}
				}
			}
			for (var i in lastList) {
				if (o[i] === undefined) {
					minorscroll ();
					InfoMessage (lastList[i] + ' has quit.');
				}
			}
			onlinelist.innerHTML = x;
			lastList = o;
			if (firstUpdate) {
				firstUpdate = 0;
			}
			if (s.length > 0) {
				msgscroll ();
			}
			for (var i = 0; i < s.length; i ++) {
				if (chatElements[s[i].id] === undefined) {
					chatElements[s[i].id] = ChatMessage(s[i].posted, s[i].poster, s[i].message);
				}
				if (s[i].id > latestID) {
					latestID = s[i].id;
				}
			}
		},
		'error': function(q) {
			msgscroll ();
			InfoMessage ('Error: ' + q);
		}
	
	};

	function sendDataToServer(w) {
		var xh = GiveMeXHR();
		var o = [];
		for (var i in w)
			o.push (i + '=' + encodeURIComponent(w[i]));
		o.push ('csrf_token=' + DtTvB_CHAT_CSRF);
		xh.open ('POST', DtTvB_CHAT_GATEWAY, true);
		xh.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		xh.onreadystatechange = function() {
			if (xh.readyState != 4) {
				return;
			}
			var q = eval('(' + xh.responseText + ')');
			if (responders[q.method] !== undefined) {
				responders[q.method] (q.result);
			}
		};
		xh.send (o.join('&'));
	}

	function reloadChatData() {
		setTimeout (reloadChatData, 3000);
		sendDataToServer ({
			'since_id': latestID
		});
	}
	reloadChatData ();

















})();
